home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / dev / c / Asyncio.lha / asyncio.doc next >
Text File  |  1995-08-12  |  16KB  |  408 lines

  1. TABLE OF CONTENTS
  2.  
  3. asyncio/--changes---
  4. asyncio/--background--
  5. asyncio/CloseAsync
  6. asyncio/OpenAsync
  7. asyncio/ReadAsync
  8. asyncio/ReadCharAsync
  9. asyncio/SeekAsync
  10. asyncio/WriteAsync
  11. asyncio/WriteCharAsync
  12. asyncio/--changes--                                       asyncio/--changes--
  13.  
  14. This version of the package (called release 3) is dated 12-Aug-95. All
  15. changes herein were made by Magnus Holmgren (with some inspiration from the
  16. asyncio code found in the AIFF datatype, by Olaf `Olsen' Barthel). I've
  17. been in contact with Martin Taillefer, and he is aware of this release.
  18. However, he is not informed about the actual details of the changes in the
  19. code. Thus, any comments about the code (especially the changes) should not
  20. be sent to him.
  21.  
  22. This version includes a couple of enhancements (most from the AIFF sources)
  23. and a couple of bugfixes to SeekAsync():
  24.  
  25.   - SeekAsync() is now not unecessarely slow when doing some "kinds" of
  26.     read-mode seeks (typically when seeking after some small amount of
  27.     initial read). The problem was that it usually only considered the
  28.     newly arrived buffer, not both buffers. This could make it discard both
  29.     buffers, and restart reading, although one of the buffers already had
  30.     the needed data. Note that the kind of seeks that caused the above
  31.     problem may still seem to be somewhat slow, since the code must wait
  32.     for both buffers to be loaded. This cannot (easily) be avoided.
  33.  
  34.   - SeekAsync() doesn't cause the read buffer to contain garbage after
  35.     certain seeks any more. The problem was that ReadAsync() would read
  36.     from the wrong buffer (the one currently being loaded). This made the
  37.     files seem to contain garbage. This happened when the seek location
  38.     was within the newly arrived buffer.
  39.  
  40.   - The code package is now supplied as a link library, rather than a
  41.     single source module. The internal functions labeled "AS_#?" are
  42.     private and should not be called directly by the application.
  43.  
  44.   - A few minor "cosmetic" changes were done, to either make the code more
  45.     readable, or to make it slightly smaller.
  46.  
  47.   - Include file restructured a little (a public and a private part).
  48.     
  49.   - OpenAsync() now offers some new "options" (all from the AIFF code by
  50.     Olaf Barthel):
  51.     1) Opening a file from an already open filehandle is now possible.
  52.     2) A "no externals" version may be compiled, that doesn't require any
  53.        external variables to be available.
  54.     3) Each of the buffers will now be roughly bufferSize / 2 bytes large,
  55.        rather than bufferSize bytes.
  56.     4) If there isn't enough memory for the requested buffer size, the code
  57.        will try with smaller buffers (still properly "aligned") before
  58.        giving up.
  59.  
  60. The code was compiled using DICE 3.0. SAS/C or GCC should be able to
  61. compile it as well, without any changes (although I haven't tested this).
  62.  
  63. I didn't include any makefile, since I don't use one anyway! ;) Instead I
  64. use the LbMake utility in the DICE package. The Lib.Def file contains the
  65. definitions for the link library.
  66.  
  67. asyncio/--background--                                 asyncio/--background--
  68.  
  69. This documentation and source code was written by Martin Taillefer. This
  70. version of the package is dated 16-Feb-94. This version contains several
  71. bug fixes over previous versions. The most important changes are:
  72.  
  73.   - SeekAsync() now consistently works. It was getting confused when called
  74.     multiple times in a row with no intervening IO.
  75.  
  76.   - WriteAsync() would produce garbage in the destination file if it had
  77.     to bring up a "Disk is full" requester, and the user freed some room on
  78.     the disk and selected "Retry".
  79.  
  80. Reading and writing data is crucial to most applications and is in many cases a
  81. major bottleneck. Using the AmigaDOS' sophisticated file system architecture
  82. can help reduce, and sometimes eliminate, the time spent waiting for IO to
  83. complete. This package offers a few small routines that can greatly improve an
  84. application's IO performance.
  85.  
  86. Normally, an application processes a file in a manner similar to the following:
  87.  
  88.   1 - Open the file
  89.  
  90.   2 - Read some data
  91.  
  92.   3 - Process data just read
  93.  
  94.   4 - Repeat steps 2 and 3 until all data is processed
  95.  
  96.   5 - Close file
  97.  
  98. Although the above sequence works fine, it doesn't make full use of the Amiga's
  99. multitasking abilities. Step 2 in the above can become a serious bottleneck.
  100. Whenever the application needs some data by using the DOS Read() function,
  101. AmigaDOS has to put that task to sleep, and initiate a request to the file
  102. system to have it fetch the data. The file system then starts up the disk
  103. hardware and reads the data. Once the data is read, the application is woken up
  104. and can start processing the data just read.
  105.  
  106. The point to note in the above paragraph is that when the file system is
  107. reading data from disk, the application is asleep. Wouldn't it be nice if the
  108. application could keep running while data is being fetched for it?
  109.  
  110. Most Amiga hard drives make use of DMA (Direct Memory Access). DMA enables a
  111. hard drive to transfer data to memory _at the same time_ as the CPU does some
  112. work. This parallelism is what makes the set of accompanying routines so
  113. efficient. They exploit the fact that data can be transfered to memory while
  114. the application is busy processing other data.
  115.  
  116. Using the asynchronous IO routines, an application's IO happens like this:
  117.  
  118.   1 - Open the file, ask the file system to start reading ahead
  119.  
  120.   2 - Read some data, ask the file system to read more data
  121.  
  122.   3 - Process data
  123.  
  124.   4 - Repeat steps 2 and 3 until all data is processed
  125.  
  126.   5 - Close file
  127.  
  128. Immediately after opening the file, a request is sent to the file system to get
  129. it reading data in the background. By the time the application gets around to
  130. reading the first byte of data, it is likely already in memory. That means the
  131. application doesn't need to wait and can start processing the data. As soon as
  132. the application starts processing data from the file, a second request is sent
  133. out to the file system to fill up a second buffer. Once the application is done
  134. processing the first buffer, it starts processing the second one. When this
  135. happens, the file system starts filling up the first buffer again with new
  136. data. This process continues until all data has been read.
  137.  
  138. The whole technique is known as "double-buffered asynchronous IO" since it uses
  139. two buffers, and happens in the background (asynchronously).
  140.  
  141. The set of functions presented below offers high-performance IO using the
  142. technique described above. The interface is very similar to standard AmigaDOS
  143. files. These routines enable full asynchronous read/write of any file.
  144.  
  145. asyncio/CloseAsync                                         asyncio/CloseAsync
  146.  
  147.    NAME
  148.     CloseAsync -- close an async file.
  149.  
  150.    SYNOPSIS
  151.     success = CloseAsync(file);
  152.  
  153.     LONG CloseAsync(struct AsyncFile *);
  154.  
  155.    FUNCTION
  156.     Closes a file, flushing any pending writes. Once this call has been
  157.     made, the file can no longer be accessed.
  158.  
  159.    INPUTS
  160.     file - the file to close. May be NULL, in which case this function
  161.            returns -1 and sets the IoErr() code to ERROR_INVALID_LOCK.
  162.            If the "no externals" version is used, then a NULL will not
  163.            set IoErr() (not possible).
  164.  
  165.    RESULT
  166.     result - < 0 for an error, >= 0 for success. Indicates whether closing
  167.          the file worked or not. If the file was opened in read-mode,
  168.              then this call will always work. In case of error,
  169.              dos.library/IoErr() can give more information.
  170.  
  171.    SEE ALSO
  172.     OpenAsync(), dos.library/Close()
  173.  
  174. asyncio/OpenAsync                                           asyncio/OpenAsync
  175.  
  176.    NAME
  177.     OpenAsync -- open a file for asynchronous IO.
  178.  
  179.    SYNOPSIS
  180.     file = OpenAsync(fileName, accessMode, bufferSize
  181.                                            [, sysbase, dosbase ] );
  182.  
  183.     struct AsyncFile OpenAsync(const STRPTR, UBYTE, LONG
  184.                        [, struct ExecBase *, struct DosLibrary * ] );
  185.  
  186.     file = OpenAsyncFromFH(handle, accessMode, bufferSize
  187.                                            [, sysbase, dosbase ] );
  188.  
  189.     struct AsyncFile OpenAsyncFromFH(BPTR, UBYTE, LONG
  190.                        [, struct ExecBase *, struct DosLibrary * ] );
  191.  
  192.    FUNCTION
  193.     The named file is opened and an async file handle returned. If the
  194.     accessMode is MODE_READ, an existing file is opened for reading.
  195.     If accessMode is MODE_WRITE, a new file is created for writing. If
  196.     a file of the same name already exists, it is first deleted. If
  197.     accessMode is MODE_APPEND, an existing file is prepared for writing.
  198.     Data written is added to the end of the file. If the file does not
  199.     exists, it is created.
  200.  
  201.     'fileName' is a filename and CANNOT be a window specification such as
  202.     CON: or RAW:, or "*"
  203.  
  204.     'bufferSize' specifies the size of the IO buffer to use. There are
  205.     in fact two buffers allocated, each of roughly (bufferSize/2) bytes
  206.     in size. The actual buffer size use can vary slightly as the size
  207.     is rounded to speed up DMA.
  208.  
  209.     If the file cannot be opened for any reason, the value returned
  210.     will be NULL, and a secondary error code will be available by
  211.     calling the routine dos.library/IoErr().
  212.  
  213.     INPUTS
  214.     name - name of the file to open, cannot be a window specification.
  215.     handle - file handle to use async io on. The file pointer must be
  216.          located at the start of the file, and you may not access
  217.          it during the life of the AsyncFile handle. After CloseAsync,
  218.          you are responsible of closing the file.
  219.     accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
  220.     bufferSize - size of IO buffer to use. 8192 is recommended as it
  221.              provides very good performance for relatively little
  222.              memory.
  223.     sysbase - Library base needed for the "no externals" version of the
  224.         library.
  225.     dosbase - Library base, as sysbase.
  226.  
  227.     RESULTS
  228.     file - an async file handle or NULL for failure. You should not access
  229.            the fields in the AsyncFile structure, these are private to the
  230.            async IO routines. In case of failure, dos.library/IoErr() can
  231.            give more information.
  232.  
  233.     NOTES (by MH)
  234.     Although stated that CON:, RAW:, or "*" cannot be used as the file
  235.     name, tests indicates that the "Console:" volume is safe to use for
  236.     writing at least. No guarantees though.
  237.  
  238.     SEE ALSO
  239.     CloseAsync(), dos.library/Open()
  240.  
  241. asyncio/ReadAsync                                           asyncio/ReadAsync
  242.  
  243.    NAME
  244.     ReadAsync -- read bytes from an async file.
  245.  
  246.    SYNOPSIS
  247.     actualLength = ReadAsync(file, buffer, numBytes);
  248.  
  249.     LONG ReadAsync(struct AsyncFile *, APTR, LONG);
  250.  
  251.    FUNCTION
  252.     This function reads bytes of information from an opened async file
  253.         into the buffer given. 'numBytes' is the number of bytes to read from
  254.         the file.
  255.  
  256.     The value returned is the length of the information actually read.
  257.     So, when 'actualLength' is greater than zero, the value of
  258.     'actualLength' is the the number of characters read. Usually
  259.     ReadAsync() will try to fill up your buffer before returning. A value
  260.     of zero means that end-of-file has been reached. Errors are indicated
  261.     by a value of -1.
  262.  
  263.     INPUTS
  264.     file - opened file to read, as obtained from OpenAsync()
  265.     buffer - buffer where to put bytes read
  266.     numBytes - number of bytes to read into buffer
  267.  
  268.     RESULT
  269.     actualLength - actual number of bytes read, or -1 if an error. In
  270.                case of error, dos.library/IoErr() can give more
  271.                information.
  272.  
  273.     SEE ALSO
  274.     OpenAsync(), CloseAsync(), ReadCharAsync(), WriteAsync(),
  275.     dos.library/Read()
  276.  
  277. asyncio/ReadCharAsync                                   asyncio/ReadCharAsync
  278.  
  279.    NAME
  280.     ReadCharAsync -- read a single byte from an async file.
  281.  
  282.    SYNOPSIS
  283.     byte = ReadCharAsync(file);
  284.  
  285.     LONG ReadCharAsync(struct AsyncFile *);
  286.  
  287.    FUNCTION
  288.     This function reads a single byte from an async file. The byte is
  289.     returned, or -1 if there was an error reading, or if the end-of-file
  290.     was reached.
  291.  
  292.    INPUTS
  293.     file - opened file to read from, as obtained from OpenAsync()
  294.  
  295.    RESULT
  296.     byte - the byte read, or -1 if no byte was read. In case of error,
  297.            dos.library/IoErr() can give more information. If IoErr()
  298.            returns 0, it means end-of-file was reached. Any other value
  299.            indicates an error.
  300.  
  301.    SEE ALSO
  302.     OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync()
  303.     dos.library/Read()
  304.  
  305. asyncio/SeekAsync                                           asyncio/SeekAsync
  306.  
  307.    NAME
  308.     SeekAsync -- set the current position for reading or writing within
  309.              an async file.
  310.  
  311.    SYNOPSIS
  312.     oldPosition = SeekAsync(file, position, mode);
  313.  
  314.     LONG SeekAsync(struct AsyncFile *, LONG, BYTE);
  315.  
  316.    FUNCTION
  317.     SeekAsync() sets the read/write cursor for the file 'file' to the
  318.     position 'position'. This position is used by the various read/write
  319.     functions as the place to start reading or writing. The result is the
  320.     current absolute position in the file, or -1 if an error occurs, in
  321.     which case dos.library/IoErr() can be used to find more information.
  322.     'mode' can be MODE_START, MODE_CURRENT or MODE_END. It is used to
  323.     specify the relative start position. For example, 20 from current
  324.     is a position 20 bytes forward from current, -20 is 20 bytes back
  325.     from current.
  326.  
  327.     To find out what the current position within a file is, simply seek
  328.     zero from current.
  329.  
  330.     INPUTS
  331.     file - an opened async file, as obtained from OpenAsync()
  332.     position - the place where to move the read/write cursor
  333.     mode - the mode for the position, one of MODE_START, MODE_CURRENT,
  334.            or MODE_END.
  335.  
  336.     RESULT
  337.     oldPosition - the previous position of the read/write cursor, or -1
  338.               if an error occurs. In case of error, dos.library/IoErr()
  339.               can give more information.
  340.  
  341.     NOTES (by MH)
  342.     If you seek after having read only a few bytes, the function must
  343.     wait for both buffers to be loaded, before the seek can be done.
  344.     This can cause small delays. Note that the above case isn't the
  345.     only one, but the typical one.
  346.  
  347.     SEE ALSO
  348.     OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
  349.     dos.library/Seek()
  350.  
  351. asyncio/WriteAsync                                         asyncio/WriteAsync
  352.  
  353.    NAME
  354.     WriteAsync -- write data to an async file.
  355.  
  356.    SYNOPSIS
  357.     actualLength = WriteAsync(file, buffer, numBytes);
  358.  
  359.     LONG WriteAsync(struct AsyncFile *, APTR, LONG);
  360.  
  361.    FUNCTION
  362.     WriteAsync() writes bytes of data to an opened async file. 'numBytes'
  363.     indicates the number of bytes of data to be transferred. 'buffer'
  364.     points to the data to write. The value returned is the length of
  365.     information actually written. So, when 'numBytes' is greater than
  366.     zero, the value of 'numBytes' is the number of characters written.
  367.     Errors are indicated by a return value of -1.
  368.  
  369.     INPUTS
  370.     file - an opened file, as obtained from OpenAsync()
  371.     buffer - address of data to write
  372.     numBytes - number of bytes to write to the file
  373.  
  374.     RESULT
  375.     actualLength - number of bytes written, or -1 if error. In case
  376.                of error, dos.library/IoErr() can give more
  377.                information.
  378.  
  379.     SEE ALSO
  380.     OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
  381.     dos.library/Write()
  382.  
  383. asyncio/WriteCharAsync                                 asyncio/WriteCharAsync
  384.  
  385.    NAME
  386.     WriteCharAsync -- write a single byte to an async file.
  387.  
  388.    SYNOPSIS
  389.     result = WriteCharAsync(file, byte);
  390.  
  391.     LONG WriteCharAsync(struct AsyncFile *, UBYTE);
  392.  
  393.    FUNCTION
  394.     This function writes a single byte to an async file.
  395.  
  396.    INPUTS
  397.     file - an opened async file, as obtained from OpenAsync()
  398.     byte - byte of data to add to the file
  399.  
  400.    RESULT
  401.     result - 1 if the byte was written, -1 if there was an error. In
  402.          case of error, dos.library/IoErr() can give more information.
  403.  
  404.    SEE ALSO
  405.     OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
  406.     dos.library/Write()
  407.  
  408.